package com.nulldev.util.security.encryptAPI.impls.experimental.shifter;

import com.nulldev.util.codecs.uniapi.UniBase64;
import com.nulldev.util.data.Charsets.CharsetUtil;

/**
 * WARNING: This is an experimental encryption method! <br>
 * Use at your OWN risk. <br>
 * Backported from 2.x. <br>
 * How encryption works: <br>
 * - call calcValue(String) on the password which adds up the char value to an
 * int. <br>
 * - shifts every byte in a string by calcValue and length. <br>
 * How decryption works: <br>
 * - call calcValue(String) on the password which adds up the char value to an
 * int. <br>
 * - shifts every byte in a string by calcValue and length in reverse.<br>
 * <br>
 * <br>
 * Is this secure and should be used in actual cryptography: <b>NO</b>
 * 
 * @author null
 */
public class Shifter {
	public String encrypt(final String text, final String password) {
		return UniBase64.encodeFromBytes(encryptBytes(text.getBytes(CharsetUtil.UTF_8), password));
	}

	public String encrypt(final String text, final String password, final int offset) {
		return UniBase64.encodeFromBytes(encryptBytes(text.getBytes(CharsetUtil.UTF_8), password, offset));
	}

	public byte[] encryptBytes(final byte[] data, final byte[] password) {
		return encryptBytes(data, new String(password));
	}

	public byte[] encryptBytes(final byte[] data, final String password) {
		final int totalValue = __calc_shifter(password);
		for (int i = 0; i < data.length; i++) {
			data[i] = (byte) (data[i] + totalValue + password.length());
		}
		return data;
	}

	public byte[] encryptBytes(final byte[] data, final String password, final int offset) {
		final int totalValue = __calc_shifter(password);
		for (int i = 0; i < data.length; i++) {
			data[i] = (byte) (data[i] + totalValue + password.length() + offset);
		}
		return data;
	}

	public String decrypt(final String text, final String password) {
		return new String(decryptBytes(UniBase64.decodeToBytes(text), password));
	}

	public String decrypt(final String text, final String password, final int offset) {
		return new String(decryptBytes(UniBase64.decodeToBytes(text), password, offset));
	}

	public byte[] decryptBytes(final byte[] data, final byte[] password) {
		return decryptBytes(data, new String(password));
	}

	public byte[] decryptBytes(final byte[] data, final String password) {
		final int totalValue = __calc_shifter(password);
		for (int i = 0; i < data.length; i++) {
			data[i] = (byte) (data[i] - totalValue - password.length());
		}
		return data;
	}

	public byte[] decryptBytes(final byte[] data, final String password, final int offset) {
		final int totalValue = __calc_shifter(password);
		for (int i = 0; i < data.length; i++) {
			data[i] = (byte) (data[i] - totalValue - password.length() - offset);
		}
		return data;
	}

	private static int __calc_shifter(final String password) {
		int out = 0;
		for (final char c : password.toCharArray()) {
			out += c;
		}
		if (out >= 65535) {
			out /= 10;
		}
		return out;
	}
}
